package org.jack.demo.formula.component;

import jdk.nashorn.api.scripting.NashornScriptEngine;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;
import org.jack.demo.formula.component.g4.FormulaLexer;
import org.jack.demo.formula.component.g4.FormulaParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class FormulaComponent {

  @Autowired
  protected NashornScriptEngine scriptEngine;

  public Object executeFormula(Map<String, String> cellMap, String formula) {
    String directive = null;
    try {
      directive = parseFormula(cellMap, formula);
      return scriptEngine.eval(directive);
    } catch (Throwable e) {
      throw new RuntimeException("Execute the script error: " + formula + ", directive: " + directive, e);
    }
  }

  public String parseFormula(Map<String, String> cellMap, String formula) {
    // 造词法分析器
    FormulaLexer formulaLexer = new FormulaLexer(CharStreams.fromString(formula));
    // 用词法分析器构造Token流
    TokenStream tokenStream = new CommonTokenStream(formulaLexer);
    // 用Token流构造语法解析器
    FormulaParser parser = new FormulaParser(tokenStream);
    // 添加异常监听器
    parser.addErrorListener(FormulaParserErrorListener.instance);
    // 生成抽象语法树
    FormulaParser.FormulaContext context = parser.formula();
    // 访问抽象语法树
    // 1.从中提取出表示单元格的ID并替换成目标单元格的值
    // 2.将函数替换成目标函数
    FormulaParserVisitor parserVisitor = new FormulaParserVisitor(cellMap);
    return parserVisitor.accept(context);
  }

}
